﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<array>
#include<type_traits>
#include<algorithm>
using namespace std;
//int size()
//{
//
//	int n = 10;
//	return n;
//}
constexpr int size()
{
	return 10;
}
constexpr int func(int x)
{
	return 10 + x;
}
constexpr int factorial(int n)
{
	return n <= 1 ? 1 : n * factorial(n - 1);
}
constexpr int fxx(int x)
{
	int i = x;
	i++;
	//cout << i << endl;
	return 10 + x;
}
constexpr int fffff(int c)
{
	return c * 20;
}
//
//int main()
//{
//	// 编译时，N会被直接替换为10，constexpr函数默认就是inline
//	constexpr int N1 = size();
//	int arr1[N1];
//	constexpr int N2 = func(10);
//	int arr2[N2];
//	constexpr	int i = 10;
//	// func传10时，func函数返回值是常量表达式，所以N2是常量表达式
//
//		// func传10时，func函数返回值是常量表达式，所以N2是常量表达式
////i作为变量的时候,在编译期间无法确定
//
//	constexpr int N3 = func(i);  // 报错func返回的不是常量表达式
//
//	int N4 = func(i);
//	// 不报错constexpr函数返回的不⼀是常量表达式
//
//	constexpr int fact5 = factorial(5);  // 编译时计算
//
//	//constexpr修饰的函数可以有⼀些其他语句，但是这些语句运⾏时可以不执⾏任何操作就可以
//
//	// 如类型别名、空语句、using声明等
//	//int c = 20;
//	constexpr int N22 = fffff(20);
//	//constexpr int N5 = fxx(10);  // c++11并不支持在constexpr修饰的函数中增加其他的控制流
//	/*constexpr int c = 1;
//	const int d = c;
//	const const int* p3 = &d;*/constexpr int c = 1;
//	static const int d = c;
//	constexpr const int* p3 = &d;
//
//	return 0;
//}
//int main()
//{
//	const int a = 1;
//	int c = 1;
//	const int d = c;
//	 a是常量表达式
//
//		const int b = a + 1;    // b是常量表达式
//
//		 c不是常量表达式
//
//		 d不是常量表达式
//
//		const int e = size();   // e不是常量表达式
//
//	constexpr int aa = 1;
//	constexpr int bb = aa + 1;
//		const  int* p1 = &d;
//	constexpr int cc = e + 1;
//	 return 0;
//}
class Date
{
public:
	constexpr Date(int year, int month, int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		//cout << "constexpr Date(int year, int month, int day)" << endl;
	}
	constexpr int GetYear() const 
	{
	//	_year++;

		return _year;
	}
private:
	int _year;
	int _month;
	int _day;
};
template<typename T>
constexpr T Func(T t)
{
	return t;
}
constexpr size_t stringLength(const char* str) {
	size_t len = 0;
	while (str[len] != '\0')
		++len;
	return len;
}
struct Point {
	constexpr Point(double x, double y) : x(x), y(y) {}
	double x, y;
};
constexpr Point midpoint(Point a, Point b) {
	return Point((a.x + b.x) / 2, (a.y + b.y) / 2);
}
constexpr std::array<int, 5> createArray() {
	std::array<int, 5> arr{};
	for (size_t i = 0; i < arr.size(); ++i) {
		arr[i] = i * i;
	}
	//delete arr;
	return arr;
}
constexpr int fibonacci(int n) {
	return (n <= 1) ? n : (fibonacci(n - 1) + fibonacci(n - 2));
}

template <class T>
auto get_value(T t)
{
	if constexpr (is_pointer_v<T>)
	{
		return *t;
	}
	else {
		return t;
	}
}
constexpr int  dynamic_memory_example()
{
	int* pr = new int(222);
	int value = *pr;
	delete pr;
	return value;
}
constexpr auto sort_example() {
	std::array<int, 5> arr{ 5, 3, 4, 1, 2 };
	std::sort(arr.begin(), arr.end());  // 	编译期排序

		return arr;
}
constexpr int safe_divide(int a, int b) {
	try {
		if (b == 0)
			throw "Division by zero";
		else
			return a / b;
	}
	catch (...) {
		return 0;  // 编译期异常处理

	}
}
union Data {
	int i;
	float f;
	
		constexpr Data(int val) : i(val) {}  // 初始化整数成员

		constexpr Data(float val) : f(val) {} // 初始化浮点成员

};
class A {
	mutable int _i;
	int _j;
public:
	constexpr A(int i, int j)
		:_i(i)
		, _j(j)
	{
	}
	
		constexpr int Func() const
	{
		++_i;
		// 可以修改

			//++_j; // 不能修改

			return _i + _j;
	}
};
void test()
{
	volatile const int a1 = 1;
	volatile const int* a2 = &a1;
	*(int*)a2 = 3;
	cout << *a2 << endl;
	cout << a1 << endl;
}
class base
{
public:
	virtual constexpr int red() const
	{
		return 1;
	}
};
class base1 :public base
{
public:
	virtual constexpr int red()  const override
	{
		return 2;
	}
};
constexpr int test1(const base& s1)
{
	return s1.red();
}
void test1()
{
	int i = 0;
	int& ri = i;
	const int ci = 42;   // 顶层	const
		int* const p1 = &i;  // 顶层	const
		const int* p2 = &ci; // 	底层	const
		const int& ri1 = ci; // 底层	const
		const int& ri2 = i;  // 底层	const
		auto j = ri;
	j++;
	auto k = i;
	k++;
	// j	类型为	int
		// k	类型为	int
		auto r1 = ci;
	r1++;
	auto r2 = p1;
	r2++;
	auto r3 = p2;
	// (*r3)++;          
	// r1	类型为	int	，忽略掉顶层		const
		// 	报错

		auto r4 = ri1;
	//const	被忽略掉了

		r4++;
	auto r5 = ri2;
	r5++;
	auto& r8 = ri1;
	auto& r9 = ri2;
	//r7++;              
	// r2	类型为	int*	，忽略掉顶层	const
		// r3	类型为	const int*	，保留底层		const
		// r4	类型为	int	，因为		ri1		是		ci	的别名，		ci	本⾝的	const是⼀个顶层
		// r5	类型为int
		const auto r7 = ci;  // r7	类型为	const int
		// r8	类型为const int&
		auto& r10 = ci;
	auto& r11 = ri;
	// r9	类型为	const int&
		// r10	类型为const int&
		// r11类型为	int&	// 	报错

		//r8++;              
		//r9++;              
		//r10++;             
		r11++;
}
int main()
{

	cout<<test1(base());
	cout<<test1(base1());
	test();
	constexpr Data d3(42);
	constexpr Data d4(3.14f);
	constexpr int temp = d3.i;
	constexpr int aaaaa = safe_divide(10,10);
	Point p1 = midpoint({ 1.1,1.1 }, { 2.2,2.2 });
	constexpr Point p2 = midpoint({ 1.1,1.1 }, { 2.2,2.2 });
	//constexpr std::array<int, 5> a1 = createArray();
	constexpr int fibArray[] = {
	fibonacci(0), fibonacci(1), fibonacci(2), fibonacci(3),
	fibonacci(4), fibonacci(5), fibonacci(6), fibonacci(7)
	};

	constexpr int x = 2025;
	//constexpr Date d0(x, 9, 8); // 报错
	constexpr auto lamada = [x](int a)constexpr->int {return x * a * a; };
	constexpr int ret6 = lamada(22);
	constexpr Date d1(2025, 9, 8);
	constexpr int y = d1.GetYear();
	Date d2(2025, 8, 11);
	int z = d2.GetYear();
	string ret1 = Func("111111"); // 普通函数

	constexpr int ret2 = Func(10);
	constexpr int ret3 = fxx(3);
	constexpr size_t ret4 = stringLength("hello");
	cout << ret4 << endl;
	int ret5 = 2222;
	cout << get_value(&ret5) << endl;
	cout << dynamic_memory_example() << endl;
	constexpr array<int, 5> arr = sort_example();
	for (auto& a : arr)
	{
		cout << a << " ";

	}
	constexpr array<int, 10> a1 = { 3,2,1,4,5 };
	// constexpr auto it2 = find(a1.begin(), a1.end(), 4);
	//static_assert(it2 != a1.end());
//	static_assert(*it2 == 4,"编译期查找");
	return 0;
}